/*
 * Java Tee Stream Library Copyright (c) Matthew Johnson 2005 This program is
 * free software; you can redistribute it and/or modify it under the terms of
 * the GNU Lesser General Public License as published by the Free Software
 * Foundation, version 2 only. This program is distributed in the hope that it
 * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
 * General Public License for more details. You should have received a copy of
 * the GNU Lesser General Public License along with this program; if not, write
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA. To Contact the author, please email
 * src@matthew.ath.cx
 */

package cx.ath.matthew.io;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * Class to copy a stream to a file or another stream as it is being sent
 * through a stream pipe E.g.
 * 
 * <pre>
 * Reader r = new InputStreamReader(new TeeInputStream(new FileInputStream(&quot;file&quot;), new File(&quot;otherfile&quot;)));
 * </pre>
 */
public class TeeInputStream extends FilterInputStream {
  private OutputStream fos;
  private InputStream  in;

  /**
   * Create a new TeeInputStream on the given InputStream and copy the stream to
   * the given File.
   * 
   * @param is
   *          Reads from this InputStream
   * @param f
   *          Write to this File
   */
  public TeeInputStream(InputStream is, File f) throws IOException {
    super(is);
    in = is;
    fos = new FileOutputStream(f);
  }

  /**
   * Create a new TeeInputStream on the given InputStream and copy the stream to
   * the given File.
   * 
   * @param is
   *          Reads from this InputStream
   * @param f
   *          Write to this File
   * @param append
   *          Append to file not overwrite
   */
  public TeeInputStream(InputStream is, File f, boolean append) throws IOException {
    super(is);
    in = is;
    fos = new FileOutputStream(f, append);
  }

  /**
   * Create a new TeeInputStream on the given InputStream and copy the stream to
   * the given File.
   * 
   * @param is
   *          Reads from this InputStream
   * @param tos
   *          Write to this OutputStream
   */
  public TeeInputStream(InputStream is, OutputStream tos) throws IOException {
    super(is);
    in = is;
    fos = tos;
  }

  /**
   * Create a new TeeInputStream on the given InputStream and copy the stream to
   * the given File.
   * 
   * @param is
   *          Reads from this InputStream
   * @param f
   *          Write to this File
   */
  public TeeInputStream(InputStream is, String f) throws IOException {
    this(is, new File(f));
  }

  /**
   * Create a new TeeInputStream on the given InputStream and copy the stream to
   * the given File.
   * 
   * @param is
   *          Reads from this InputStream
   * @param f
   *          Write to this File
   * @param append
   *          Append to file not overwrite
   */
  public TeeInputStream(InputStream is, String f, boolean append) throws IOException {
    this(is, new File(f), append);
  }

  @Override
  public int available() throws IOException {
    return in.available();
  }

  @Override
  public void close() throws IOException {
    in.close();
    fos.close();
  }

  @Override
  public void finalize() {
    try {
      close();
    } catch (Exception e) {
    }
  }

  public void flush() throws IOException {
    fos.flush();
  }

  @Override
  public void mark(int readlimit) {
  }

  @Override
  public boolean markSupported() {
    return false;
  }

  @Override
  public int read() throws IOException {
    int i = in.read();
    if (-1 != i) {
      fos.write(i);
    }
    return i;
  }

  @Override
  public int read(byte[] b) throws IOException {
    int c = in.read(b);
    if (-1 != c) {
      fos.write(b, 0, c);
    }
    return c;
  }

  @Override
  public int read(byte[] b, int off, int len) throws IOException {
    int c = in.read(b, off, len);
    if (-1 != c) {
      fos.write(b, off, c);
    }
    return c;
  }

  @Override
  public void reset() throws IOException {
    in.reset();
  }

  @Override
  public long skip(long n) throws IOException {
    return in.skip(n);
  }
}
